package com.njcb.ams.store.esbmodule.interceptor;

import com.njcb.ams.pojo.enumvalue.TransStatusCode;
import com.njcb.ams.portal.SysBaseDefine;
import com.njcb.ams.repository.entity.SysTradeLog;
import com.njcb.ams.store.esbmodule.Constants;
import com.njcb.ams.store.esbmodule.EsbHeadUtil;
import com.njcb.ams.store.esbmodule.SysHeadBean;
import com.njcb.ams.support.comm.SequenceService;
import com.njcb.ams.support.exception.ExceptionUtil;
import com.njcb.ams.support.trade.TradeUtil;
import com.njcb.ams.util.*;
import com.thoughtworks.xstream.XStream;
import org.apache.commons.lang.StringUtils;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.invoker.MethodDispatcher;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;

/**
 * CXF请求拦截器
 * @author LOONG
 */
@Component
public class ReqInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
    private static final Logger logger = LoggerFactory.getLogger(RspInterceptor.class);

    private static XStream xStream = new XStream();

    @Autowired
    private SequenceService sequenceService;

    public ReqInterceptor() {
        super(Phase.PREPARE_SEND);
    }

    public ReqInterceptor(String phase) {
        super(phase);
    }

    @Override
    public void handleMessage(SoapMessage message) {
        SysTradeLog tradeLog = initTradeLog();
        Exchange exchange = message.getExchange();
        BindingOperationInfo bp = exchange.get(BindingOperationInfo.class);
        Service service = exchange.get(Service.class);
        MethodDispatcher m = (MethodDispatcher) service.get(MethodDispatcher.class.getName());
        Method method = m.getMethod(bp);
        List<Object> list = CastUtils.cast(message.getContent(List.class));
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (parameterTypes.length == 1) {
            Object param = list.get(0);
            try {
                Method getReqSysHead = null;
                SysHeadBean sysHeadBean = null;
                try {
                    if (null != param) {
                        getReqSysHead = param.getClass().getDeclaredMethod("getReqSysHead");
                        sysHeadBean = transformSysHead(getReqSysHead, param);
                    } else {
                        param = parameterTypes[0].newInstance();
                        sysHeadBean = initReqSysHeadType(null);
                    }
                } catch (NoSuchMethodException e) {
                    logger.warn("未遵循南京银行ESB规范,没有ESB头信息");
                    sysHeadBean = initReqSysHeadType(null);
                }

                tradeLog.setReqSeq(sysHeadBean.getReqSeq());
                tradeLog.setGlobalSeq(AmsUtils.isNotNull(sysHeadBean.getGlobalSeq()) ? sysHeadBean.getGlobalSeq() : SequenceService.getGlobalSeq());
                tradeLog.setTradeCode(sysHeadBean.getServiceID() + sysHeadBean.getSvcScn());
                if (null == sysHeadBean.getServiceID()) {
                    tradeLog.setTradeCode(param.getClass().getSimpleName());
                }
                tradeLog.setTradeName("WebService");
                tradeLog.setTradeType(SysTradeLog.TRADETYPE_20);
                if (null != EsbHeadUtil.getSrcSysHead()) {
                    tradeLog.setGlobalSeq(EsbHeadUtil.getSrcSysHead().getGlobalSeq());
                }
            } catch (Exception e) {
                ExceptionUtil.printStackTrace(e);
                logger.error("发送报文预处理异常");
                ExceptionUtil.throwAppException(e.getMessage());
            }
            logger.info("\n请求报文\n" + xStream.toXML(param));
        }
        message.setContent(List.class, list);
        bp.setProperty(Constants.CXF_LOG_STORAGE_PROPERTY, tradeLog);
    }

    private SysHeadBean transformSysHead(Method getReqSysHead, Object param) throws Exception {
        Object reqSysHead = getReqSysHead.invoke(param);
        SysHeadBean sysHeadBean = initReqSysHeadType(reqSysHead);
        if (null == reqSysHead) {
            Class<?> returnType = getReqSysHead.getReturnType();
            reqSysHead = returnType.newInstance();
        }
        AmsBeanUtils.copyProperties(reqSysHead, sysHeadBean);
        Method[] methodArray = param.getClass().getDeclaredMethods();
        Method setReqSysHead = null;
        for (Method tmpMethod : methodArray) {
            if ("setReqSysHead".equals(tmpMethod.getName())) {
                setReqSysHead = tmpMethod;
            }
        }
        AmsAssert.notNull(setReqSysHead, "头函数错误");
        setReqSysHead.invoke(param, reqSysHead);
        return sysHeadBean;
    }

    public SysHeadBean initReqSysHeadType(Object inSysHeadBean) {
        SysHeadBean reqSysHead = new SysHeadBean();
        if (null == inSysHeadBean) {
            inSysHeadBean = new SysHeadBean();
        }
        AmsBeanUtils.copyProperties(reqSysHead, inSysHeadBean);
        // 系统编码
        String reqSysID = SysInfoUtils.getSysId();
        // 渠道标识
        String channelID = SysInfoUtils.getChannelId();
        // 发起方法人机构代码
        String legOrgID = "9999";
        // 日期
        String dateStr8 = AmsDateUtils.getCurrentDate8();
        // 日期
        String dateStr6 = AmsDateUtils.getCurrentDate6();
        // 日期
        String timeStr6 = AmsDateUtils.getCurrentTime6();
        String ipStr = "000.000.000.000";
        try {
            // IP地址
            ipStr = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
        }
        // 流水
        String reqSeq = "000000000000";
        if (AmsUtils.isNotNull(EsbHeadUtil.getReqSeq())) {
            reqSeq = EsbHeadUtil.getReqSeq();
        } else if (StringUtils.isEmpty(reqSysHead.getReqSeq()) && null != sequenceService) {
            reqSeq = sequenceService.genSeqStr("REQSEQ");
        }

        // 系统编码
        if (StringUtils.isNotEmpty(reqSysHead.getReqSysID())) {
            reqSysID = reqSysHead.getReqSysID();
        } else if (null != EsbHeadUtil.getReqSysID()) {
            reqSysID = EsbHeadUtil.getReqSysID();
        }

        // 渠道标识
        if (StringUtils.isNotEmpty(reqSysHead.getChannelID())) {
            channelID = reqSysHead.getChannelID();
        } else if (null != EsbHeadUtil.getChannelID()) {
            channelID = EsbHeadUtil.getChannelID();
        }

        String globalSeq = EsbHeadUtil.getGlobalSeq();
        if (AmsUtils.isNull(globalSeq)) {
            globalSeq = TradeUtil.getGlobalSeq();
        }
        if (AmsUtils.isNull(globalSeq)) {
            globalSeq = "G" + reqSysID + dateStr6 + "000" + reqSeq.substring(3) + "00"; // 全局序号
        }
        // 报文长度
        reqSysHead.setPkgLength(Constants.PKGLENGTH_DEFAULT);
        // 发起方渠道标识
        reqSysHead.setChannelID(channelID);
        // 发起方法人机构代码
        reqSysHead.setLegOrgID(legOrgID);
        // 请求系统日期
        reqSysHead.setReqDate(dateStr8);
        // 请求系统时间
        reqSysHead.setReqTime(timeStr6);
		// MAC校验值
        reqSysHead.setMAC(Constants.MAC_DEFAULT);
		// 服务版本号 默认01.000
        reqSysHead.setVersion(Constants.VERSION_DEFAULT);
		// 请求运行优先级 默认00
        reqSysHead.setPriority(Constants.PRIORITY_DEFAULT);
		// 请求者域名地址 IP地址
        reqSysHead.setDomainRef(ipStr);
		// 接受语言
        reqSysHead.setAcceptLang(Constants.ACCEPT_LANG);
		// 一期只启用前12位作为通讯流水
        reqSysHead.setReqSeq(reqSeq);
		// 全局序号采用reqSeq
        reqSysHead.setGlobalSeq(globalSeq);
		// 请求系统标识
        reqSysHead.setReqSysID(reqSysID);
		// 发起方系统编码
        reqSysHead.setOrgSysID(reqSysID);
        if (null != EsbHeadUtil.getServiceID()) {
			// 服务代码
            reqSysHead.setServiceID(EsbHeadUtil.getServiceID());
        }
        if (null != EsbHeadUtil.getSvcScn()) {
			// 服务场景
            reqSysHead.setSvcScn(EsbHeadUtil.getSvcScn());
        }
        return reqSysHead;
    }

    private SysTradeLog initTradeLog() {
        SysTradeLog tradeLog = new SysTradeLog();
        tradeLog.setTransStatus(TransStatusCode.SUCC.getCode());
        tradeLog.setRetCode("0000");
        tradeLog.setRetMsg("交易成功");
        long startTime = System.currentTimeMillis();
        tradeLog.setTimeStamp(startTime);
        tradeLog.setTradeNode(SysBaseDefine.TRADE_NODE);
        tradeLog.setAppVersion(SysBaseDefine.APP_VERSION);
        tradeLog.setReqDate(AmsDateUtils.getCurrentDate8());
        tradeLog.setReqTime(AmsDateUtils.getCurrentTime6());
        tradeLog.setBusiSign(TradeUtil.getBusiSign());
        tradeLog.setRemark(TradeUtil.getRemark());
        return tradeLog;
    }

}
